#include <opencv2/core/mat.hpp>
#include <opencv2/imgproc.hpp>
#include <ImageView.h>
#include <DecodeHints.h>
#include <ReadBarcode.h>
#include <TextUtfEncoding.h>
#include <iostream>
#include "processor/QRDetector.h"

QRDetector::QRDetector() {
    // 默认ROI参数
    m_roiParams.centerScale = 1.1;
    m_roiParams.widthScale = 0.1;
    m_roiParams.heightScale = 1.0;
}

void QRDetector::setRoiParameters(double centerScale, double widthScale, double heightScale) {
    m_roiParams.centerScale = centerScale;
    m_roiParams.widthScale = widthScale;
    m_roiParams.heightScale = heightScale;
}

bool QRDetector::detect(const cv::Mat& inputImage) {
    // 清空历史数据
    m_markedImage.release();
    m_extractedROIs.clear();
    m_allQrCorners.clear();
    m_qrSideLengths.clear();
    m_qrContents.clear();

    if (inputImage.empty())  {
        return false;
    }

    // 转换为灰度图
    cv::Mat gray;
    cv::cvtColor(inputImage, gray, cv::COLOR_BGR2GRAY);

    // 使用ZXing检测二维码
    auto bitmap = ZXing::ImageView(gray.data,  gray.cols,  gray.rows,  ZXing::ImageFormat::Lum);
    ZXing::DecodeHints hints;
    hints.setTryHarder(true);
    hints.setFormats(ZXing::BarcodeFormat::QRCode);

    auto results = ZXing::ReadBarcodes(bitmap, hints);

    if (results.empty())  {
        std::cerr << "No QR code detected." << std::endl;
        return false;
    }

    // 准备标记图像
    m_markedImage = inputImage.clone();

    // 处理每个检测到的二维码
    for (const auto& result : results) {
        if (!result.isValid())  {
            continue;
        }

        // 获取二维码的四个角点
        auto position = result.position();
        if (position.size()  != 4) {
            continue;  // 确保有4个角点
        }

        // 转换为OpenCV的点格式
        std::vector<cv::Point> qrCorners;
        for (const auto& pt : position) {
            qrCorners.emplace_back(pt.x,  pt.y);
        }
        m_allQrCorners.push_back(qrCorners);

        // 存储二维码内容
        m_qrContents.push_back(result.text());

        // 计算底部边长（BL到BR的距离）
        double sideLength = cv::norm(qrCorners[3] - qrCorners[2]);
        m_qrSideLengths.push_back(sideLength);

        // 绘制二维码边框（绿色）和编号
        cv::polylines(m_markedImage, std::vector<std::vector<cv::Point>>{qrCorners},
                      true, cv::Scalar(0, 255, 0), 2);

        // 在二维码中心显示编号
        cv::Point center(0, 0);
        for (const auto& pt : qrCorners) {
            center += pt;
        }
        center.x /= 4;
        center.y /= 4;

        cv::putText(m_markedImage,
                    std::to_string(m_qrContents.size()),
                    center,
                    cv::FONT_HERSHEY_SIMPLEX,
                    1,
                    cv::Scalar(0, 0, 255),
                    2);

        // 处理当前二维码的ROI
        processSingleQR(qrCorners);

        // 打印二维码信息
        std::cout << "QR Code #" << m_qrContents.size()
                  << " content: " << result.text()
                  << ", position: " << qrCorners << std::endl;
    }

    return !m_allQrCorners.empty();
}

void QRDetector::processSingleQR(const std::vector<cv::Point>& qrCorners) {
    // 1. 完整转换为浮点坐标
    std::vector<cv::Point2f> qrCornersFloat;
    for (const auto& pt : qrCorners) {
        qrCornersFloat.emplace_back(pt.x, pt.y);
    }

    // 2. 使用浮点坐标进行计算
    const cv::Point2f& bottomLeft = qrCornersFloat[3]; // BL
    const cv::Point2f& bottomRight = qrCornersFloat[2]; // BR
    const double sideLength = cv::norm(bottomRight - bottomLeft);

    // 3. 计算几何参数
    cv::Point2f baseVec = bottomRight - bottomLeft;
    float angle = atan2(baseVec.y, baseVec.x);
    cv::Point2f perpendicularDir(-sin(angle), cos(angle));
    cv::Point2f baseMid = (bottomLeft + bottomRight) * 0.5f;
    cv::Point2f roiCenter = baseMid + perpendicularDir * (m_roiParams.centerScale * sideLength);

    // 4. 计算ROI角点
    float roiWidth = m_roiParams.widthScale * sideLength;
    float roiHeight = m_roiParams.heightScale * sideLength;
    cv::Point2f widthDir(cos(angle), sin(angle));

    std::vector<cv::Point2f> roiCorners = {
            roiCenter - widthDir * (roiWidth/2) - perpendicularDir * (roiHeight/2),
            roiCenter + widthDir * (roiWidth/2) - perpendicularDir * (roiHeight/2),
            roiCenter + widthDir * (roiWidth/2) + perpendicularDir * (roiHeight/2),
            roiCenter - widthDir * (roiWidth/2) + perpendicularDir * (roiHeight/2)
    };

    // // 5. 绘制时需要转换为整数坐标
    // std::vector<cv::Point> roiCornersInt;
    // for (const auto& pt : roiCorners) {
    // roiCornersInt.emplace_back(cvRound(pt.x), cvRound(pt.y));
    // }
    // cv::polylines(m_markedImage, std::vector<std::vector<cv::Point>>{roiCornersInt},
    // true, cv::Scalar(0, 0, 255), 2);

    // 6. 透视变换
    std::vector<cv::Point2f> dstCorners = {
            {0, 0}, {roiWidth, 0}, {roiWidth, roiHeight}, {0, roiHeight}
    };
    cv::Mat perspMat = cv::getPerspectiveTransform(roiCorners, dstCorners);
    cv::warpPerspective(m_markedImage, m_extractedROIs.emplace_back(),
                        perspMat, cv::Size(roiWidth, roiHeight));

    perspMat.release();

}

// Getter 实现
const std::vector<double>& QRDetector::getQrSideLengths() const {
    return m_qrSideLengths;
}

const std::vector<cv::Mat>& QRDetector::getExtractedROIs() const {
    return m_extractedROIs;
}

const cv::Mat& QRDetector::getMarkedImage() const {
    return m_markedImage;
}

const std::vector<std::vector<cv::Point>>& QRDetector::getAllQrCorners() const {
    return m_allQrCorners;
}